package word;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import word.attribute.AdditionalAttribute;
import word.attribute.AttributeList;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.Border;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.util.ArrayList;

/**
 * 단어 클래스
 */
public class Word
{
	private static final Font typeNameFont = new Font("맑은 고딕", Font.BOLD, 12);
	private static final Font nameFont = new Font("맑은 고딕", Font.PLAIN, 30);
	private static final Font meanFont = new Font("맑은 고딕", Font.PLAIN, 20);

	/**
	 * 단어의 종류 열거형
	 */
	public enum Type
	{
		NOUN("[명사]"),
		ADJECTIVE("[형용사]"),
		VERB("[동사]"),
		ADVERB("[부사]"),
		OTHER("[기타]");

		public final String name;

		Type(String name)
		{
			this.name = name;
		}

		static Type findByName(String name)
		{
			Type[] types = Type.values();
			for (Type i : types)
				if (i.name.equals(name))
					return i;

			return null;
		}
	}

	private Type   type; // 종류
	private String name; // 단어
	private String mean; // 의미

	// 단어의 추가적인 속성들
	private ArrayList<AdditionalAttribute> attributes = new ArrayList<AdditionalAttribute>();

	public boolean selected; // 선택되었는지 여부

	/**
	 * 생성자
	 * @param type : 종류
	 * @param name : 단어
	 * @param mean : 의미
	 */
	public Word(Type type, String name, String mean)
	{
		this.type = type;
		this.name = name;
		this.mean = mean;
		this.selected = false;
	}

	/**
	 * JSON 파싱해서 Word 클래스를 생성하는 메서드
	 * @param object : JSON 객체
	 * @return
	 */
	public static Word parseJSON(JSONArray object)
	{
		// 기본속성 파싱
		JSONObject basic = (JSONObject) object.get(0);
		String typeName = (String) basic.get("type");
		Type type = Type.findByName(typeName);
		String name = (String) basic.get("name");
		String mean = (String) basic.get("mean");

		Word word = null;
		if (type != null && name != null && mean != null)
			word = new Word(type, name, mean);

		// 추가속성 파싱
		JSONArray additional = (JSONArray) object.get(1);
		for (int i = 0; i < additional.size(); i++)
		{
			AdditionalAttribute attribute = AttributeList.parseJSON((JSONObject) additional.get(i));
			if (attribute != null)
				word.addAttribute(attribute);
		}

		return word;
	}

	/**
	 * 단어내용을 패널로 바꾸는 메서드
	 * @return : 단어패널
	 */
	public JPanel toPanel()
	{
		JPanel panel = new JPanel();
		panel.setBackground(Color.WHITE);

		Border empty = BorderFactory.createEmptyBorder(0, 5, 5, 5);

		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		panel.add(Box.createRigidArea(new Dimension(5, 5)));

		JLabel typeNameLabel = new JLabel(type.name);
		typeNameLabel.setFont(typeNameFont);

		JLabel nameLabel = new JLabel(name);
		nameLabel.setFont(nameFont);

		JLabel meanLabel = new JLabel(mean);
		meanLabel.setFont(meanFont);

		Box typeBox = Box.createHorizontalBox();
		typeBox.setAlignmentX(Component.LEFT_ALIGNMENT);
		typeBox.add(typeNameLabel);

		Box nameAndMeanBox = Box.createHorizontalBox();

		nameAndMeanBox.setAlignmentX(Component.LEFT_ALIGNMENT);
		nameAndMeanBox.add(nameLabel);
		nameAndMeanBox.add(Box.createRigidArea(new Dimension(7, 0)));
		nameAndMeanBox.add(meanLabel);

		panel.setAlignmentX(Component.LEFT_ALIGNMENT);
		panel.setBorder(empty);
		panel.add(typeBox);
		panel.add(nameAndMeanBox);

		for (AdditionalAttribute i : attributes)
			panel.add(i.toPanel());

		return panel;
	}

	/**
	 * 단어내용을 JSONArray 바꾸는 메서드
	 * @return : JSONArray
	 */
	public JSONArray toJson()
	{
		JSONArray object = new JSONArray();

		// 기본속성
		JSONObject def = new JSONObject();
		def.put("type", type.name);
		def.put("name", name);
		def.put("mean", mean);

		// 추가속성 배열
		JSONArray array = new JSONArray();

		for (int i = 0; i < attributes.size(); i++)
		{
			AdditionalAttribute iAttribute = attributes.get(i);
			JSONObject attributeObject = iAttribute.toJsonObject();
			attributeObject.put("name", iAttribute.getName());
			array.add(attributeObject);
		}

		object.add(def);
		object.add(array);

		return object;
	}

	/**
	 * 속성을 추가하는 메서드
	 * @param attribute : 속성
	 */
	public void addAttribute(AdditionalAttribute attribute)
	{
		attributes.add(attribute);
	}

	/**
	 * 속성들을 추가하는 메서드
	 * @param attributes : 속성리스트
	 */
	public void addAttributes(ArrayList<AdditionalAttribute> attributes)
	{
		for (AdditionalAttribute i : attributes)
			this.attributes.add(i);
	}
}